{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "fd07c17b",
   "metadata": {},
   "source": [
    "# [4、PyTorch的Dataset与DataLoader详细使用教程](https://www.bilibili.com/video/BV1yP4y1L7cC?spm_id_from=333.788.player.switch&vd_source=cdd897fffb54b70b076681c3c4e4d45d)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "0a0cf8b4",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import torchvision as tv\n",
    "from torch.utils.data import Dataset\n",
    "from torchvision import datasets\n",
    "from torchvision.transforms import ToTensor\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6bf45950",
   "metadata": {},
   "source": [
    "dataset类用于从磁盘中获取数据集，映射成xy形式。\n",
    "dataloader从dataset中获取数据，用于随机梯度下降，还会打乱、放入GPU等"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "45811a77",
   "metadata": {},
   "source": [
    "## Dataset API"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "c69e5d40",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100.0%\n",
      "100.0%\n",
      "100.0%\n",
      "100.0%\n"
     ]
    }
   ],
   "source": [
    "training_data = datasets.FashionMNIST(\n",
    "    root=\"mnist_dataset\",\n",
    "    train=True,\n",
    "    download=True,\n",
    "    transform=ToTensor()\n",
    ")\n",
    "\n",
    "test_data = datasets.FashionMNIST(\n",
    "    root=\"mnist_dataset\",\n",
    "    train=False,\n",
    "    download=True,\n",
    "    transform=ToTensor()\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3ef907e9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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qEiWLVsmIj///WwgEBARkQMHDsju3bulqqpKBgwYUPOYX6qsrJTzzz9f3n77bZk7d66ceuqpNdtmz54tBw4ckAsuuKDWPtPT06Vbt251/vNxZGSkXHLJJaF5A4EGVlxcLCIi8fHxh3zs3LlzRUTkhhtuqBW/8cYbRURq/R3gL/8uvaSkRAoKCuSkk06SsrIyWb169W8+btjxn3pDaODAgTJ79myprKyUFStWyJw5c+SBBx6QsWPHyvLly6V3794iItKpU6c6ucnJybJnz55D7qNz584hP27gcAnVmtm5c6cUFhbKtGnT1O7CXzaMPPPMM/K///u/snr1atm/f39N3LS+7r77biktLZV58+bJ0KFDa21bt26deJ4n3bp1M+4zIiKi1j936NChpugEmrqEhAQR+bk4O5RNmzZJq1atpGvXrrXi6enpkpSUJJs2baqJff/993LbbbfJRx99VFNcHlRUVBSCI4cNhV8DCAQCMnDgQBk4cKB0795dLrnkEnnllVfk9ttvFxFRu3W9ekzWoYMXLdFvXTMHDhwQEZGLLrpIJkyYYHxsv379ROTnRoyJEyfKOeecI//93/8t7dq1k/DwcLn77rtlw4YNdfJGjhwp8+fPl3vvvVeGDh0qUVFRNdsOHDggYWFhMm/ePOMx/vpvkli/aE4SEhKkffv2snLlynrnHGr8WGFhoQwZMkQSEhLkzjvvlJycHImKipJly5bJLbfcUrOW0XAo/BrYgAEDRERk+/btDbqf+sz6A5oDP2smNTVV4uPjpbq6WkaMGGF97KuvvipdunSR2bNn11o3B4vMXxs0aJBcccUVMnr0aDn//PNlzpw50rr1z1+dOTk54nmedO7cWbp3717v4wWai9GjR8u0adPkiy++kOOOO059XFZWlhw4cEDWrVsnvXr1qonn5+dLYWGhZGVliYjIwoULZdeuXTJ79mwZPHhwzeNyc3PrPCfXtYbB3/iFyIIFC4y/2B38u4cePXo06P5jY2OlsLCwQfcBhFIo10x4eLicd9558tprrxl/ndi5c2etx4rU/oX9yy+/lC+++EJ9/hEjRsiLL74o8+fPlz/84Q81v0qce+65Eh4eLlOnTq3zWjzPk127dtX7NQBN0c033yyxsbFy+eWXS35+fp3tGzZskIceekjOOOMMEZE6d9q4//77RURquuBN66+yslIee+yx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/ngpKyuT6667TlJSUuSZZ56Rs846S1599VUZM2aMiIjs27dPhg4dKuvXr5drrrlGOnfuLK+88opMnDhRCgsL5frrr5fU1FR5/PHH5corr5QxY8bIueeeKyIi/fr1q9fxNlse6uW9997zwsPDvfDwcO+4447zbr75Zu/dd9/1Kisraz2urKysTu7IkSO9Ll261IplZWV5IuJ98sknNbEdO3Z4kZGR3o033lgT++Mf/+iJiPfll1/WelxiYqInIl5ubq5131OmTPFiYmK88vLymtiECRO8rKyser92oCmp71oUES8QCHjr16+via1YscITEe+RRx6piU2fPr3OWjq4PufPn19n/7Gxsd6ECRNC/rqAYHz99deeiHjvv/++53med+DAAa9jx47e9ddfX+txubm5noh4KSkp3u7du2vib7zxhici3ltvvVUTmzBhghcbG+t5nuctWrTIS0hI8EaNGlXr+uF5njdkyBBvyJAhNf88c+ZMr1WrVt6nn35a63FPPPGEJyLeZ599Zn0tEyZM8ESkzv86dOjgLV26tNZjD14Tf7mvkpISr3Pnzl52drZXXV3teZ7nPfjgg56IeM8991zN4yorK73jjjvOi4uL84qLiz3P87ydO3d6IuLdfvvt1mNsSfhPvfV0yimnyBdffCFnnXWWrFixQu69914ZOXKkdOjQQd58882ax/3y34iKioqkoKBAhgwZIhs3bpSioqJaz9m7d2856aSTav45NTVVevToIRs3bqyJzZ07VwYNGiTHHHNMrcf9/ve/r3OMv9x3SUmJFBQUyEknnSRlZWWyevXq3/YGAE1EfdeiiMiIESNq/SLXr18/SUhIqLXGNJ07d5aRI0eG/PiBUJg1a5akpaXJySefLCI/jy+68MIL5cUXXzT+ec+FF14oycnJNf988NpjWgsLFiyQkSNHyvDhw2X27NkSGRlpPZZXXnlFevXqJT179pSCgoKa/w0bNqzm+Q4lKipK3n//fXn//ffl3XfflSeffFLi4uLkjDPOkLVr19Y8bu7cuXLMMcfIiSeeWBOLi4uTyZMnS15eXk0X8Ny5cyU9PV3Gjx9f87iIiAi57rrrpLS0VD7++ONDHlNLReEXhIEDB8rs2bNlz549smTJErn11lulpKRExo4dW3OyffbZZzJixAiJjY2VpKQkSU1NlT//+c8iInUKv06dOtXZR3JysuzZs6fmnzdt2iTdunWr87gePXrUiX3//fcyZswYSUxMlISEBElNTa35Y9lf7xtozuqzFkXqt8Y0nTt3DukxA6FSXV0tL774opx88smSm5sr69evl/Xr18uxxx4r+fn58uGHH9bJ+fVaOFgE/notlJeXy6hRo+Soo46Sl19+WQKBwCGPZ926dfL9999Lampqrf91795dROrXdBUeHi4jRoyQESNGyKmnniqTJ0+WDz74QIqKiuTWW2+tedymTZuM179evXrVbD/4f7t16yatWrWyPs5F/I2fD4FAQAYOHCgDBw6U7t27yyWXXCKvvPKKXHTRRTJ8+HDp2bOn3H///ZKZmSmBQEDmzp0rDzzwQJ2GDK2T0PO8oI+psLBQhgwZIgkJCXLnnXdKTk6OREVFybJly+SWW24xNoMAzZ22Fg92Nv6WNUYHL5qqjz76SLZv3y4vvviivPjii3W2z5o1S0499dRasfquhcjISDnjjDPkjTfekPnz59f6+zrNgQMH5IgjjpD777/fuD0zM/OQz2HSsWNH6dGjh3zyySe+8mFG4fcbDRgwQEREtm/fLm+99ZZUVFTIm2++WevfrurzM7cmKytL1q1bVye+Zs2aWv+8cOFC2bVrl8yePVsGDx5cE8/NzfW9b6A5+eVabEhhYWEN+vzAocyaNUvatWsn//d//1dn2+zZs2XOnDnyxBNP+PqXl7CwMJk1a5acffbZcv7558u8efMOeZeOnJwcWbFihQwfPjzk66OqqqpWN3FWVlad65+I1Pw508F5nFlZWfLtt9/KgQMHav3q9+vHubie+U+99bRgwQLjrwRz584VkZ//0+vBf6P65eOKiopk+vTpvvd7xhlnyOLFi2XJkiU1sZ07d9Zp2zftu7KyUh577DHf+waaovqsxYYUGxsrhYWFDboPQLNv3z6ZPXu2jB49WsaOHVvnf9dcc42UlJTU+XvXYAQCAZk9e7YMHDhQzjzzzFrXH5MLLrhAfvzxR3nqqaeMx7t3715fx7F27VpZs2aNHHnkkTWxM844Q5YsWSJffPFFTWzv3r0ybdo0yc7Olt69e9c87qeffpKXXnqp5nFVVVXyyCOPSFxcnAwZMkRERGJiYkREnFrT/OJXT9dee62UlZXJmDFjpGfPnlJZWSmff/65vPTSS5KdnS2XXHKJ5OfnSyAQkDPPPFOmTJkipaWl8tRTT0m7du18/wpx8803y8yZM+W0006T66+/vmacy8F/mzno+OOPl+TkZJkwYYJcd911EhYWJjNnzvT1n42Bpqw+a7EhHX300fLBBx/I/fffL+3bt5fOnTs369tloXl58803paSkRM466yzj9kGDBklqaqrMmjVLLrzwQt/7iY6OlrfffluGDRsmp59+unz88cfq+KQ//OEP8vLLL8sVV1whCxYskBNOOEGqq6tl9erV8vLLL9fMw7SpqqqS5557TkR+/k/HeXl58sQTT8iBAwdqDaX+05/+JC+88IKcfvrpct1110mbNm3kmWeekdzcXHnttddqft2bPHmyPPnkkzJx4kRZunSpZGdny6uvviqfffaZPPjggxIfH1/zOnv37i0vvfSSdO/eXdq0aSN9+/Y95KioZu3wNRQ3L/PmzfMuvfRSr2fPnl5cXJwXCAS8rl27etdee62Xn59f87g333zT69evnxcVFeVlZ2d799xzj/f0008bx0WMGjWqzn5+3SbveZ737bffekOGDPGioqK8Dh06eHfddZf3n//8p85zfvbZZ96gQYO86Ohor3379jVjLkTEW7BgQc3jGOeC5qy+a1FEvKuvvrpOflZWVq1xLNo4F9P69DzPW716tTd48GAvOjraExFGu6BRnXnmmV5UVJS3d+9e9TETJ070IiIivIKCgppxLvfdd1+dx8mvxpj8cpzLQQUFBV7v3r299PR0b926dZ7nma9TlZWV3j333OP16dPHi4yM9JKTk72jjz7amzp1qldUVGR9TaZxLgkJCd7w4cO9Dz74oM7jN2zY4I0dO9ZLSkryoqKivGOOOcZ7++236zwuPz/fu+SSS7y2bdt6gUDAO+KII7zp06fXedznn3/uHX300V4gEHBitEuY5/GTEAAAgAv4Gz8AAABHUPgBAAA4gsIPAADAERR+AAAAjqDwAwAAcASFHwAAgCMo/AAAABxR7zt3uHg/O7R8TXGMpStrTbtpvIhIdXW1MR4ZGanm3Hrrrca47a45HTt2NMaXLVum5syZM0fdpvnlvUJ/yXb+NcVz87doiq/HlbUGtxxqrfGLHwAAgCMo/AAAABxB4QcAAOAICj8AAABHUPgBAAA4IsyrZ6sV3U9oieg0DI7Wiat14YbaAw88oG4bO3asMf7DDz+oOa1bmwcb9O7dW81JT09XtzUGP93Q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",
      "text/plain": [
       "<Figure size 800x800 with 9 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "labels_map = {\n",
    "    0: \"T-Shirt\",\n",
    "    1: \"Trouser\",\n",
    "    2: \"Pullover\",\n",
    "    3: \"Dress\",\n",
    "    4: \"Coat\",\n",
    "    5: \"Sandal\",\n",
    "    6: \"Shirt\",\n",
    "    7: \"Sneaker\",\n",
    "    8: \"Bag\",\n",
    "    9: \"Ankle Boot\",\n",
    "}\n",
    "figure = plt.figure(figsize=(8, 8))\n",
    "cols, rows = 3, 3\n",
    "for i in range(1, cols * rows + 1):\n",
    "    sample_idx = torch.randint(len(training_data), size=(1,)).item()\n",
    "    img: torch.Tensor\n",
    "    label: torch.Tensor\n",
    "    img, label = training_data[sample_idx]\n",
    "    figure.add_subplot(rows, cols, i)\n",
    "    plt.title(labels_map[label])\n",
    "    plt.axis(\"off\")\n",
    "    plt.imshow(img.squeeze(), cmap=\"gray\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fb4c9f28",
   "metadata": {},
   "source": [
    "## 自定义Dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "713564fe",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 自定义Dataset\n",
    "import os\n",
    "import pandas as pd\n",
    "from torchvision.io import decode_image\n",
    "\n",
    "class CustomImageDataset(Dataset):\n",
    "    \"\"\"\n",
    "    这里是 map-style dataset\n",
    "    数据集格式\n",
    "    tshirt1.jpg, 0\n",
    "    tshirt2.jpg, 0\n",
    "    ......\n",
    "    ankleboot999.jpg, 9\n",
    "    \"\"\"\n",
    "    def __init__(self, annotations_file, img_dir, transform=None, target_transform=None):\n",
    "        \"\"\"创建自定义Dataset,让其知道如何拿、处理数据\n",
    "        \"\"\"\n",
    "        self.img_labels = pd.read_csv(annotations_file)\n",
    "        self.img_dir = img_dir\n",
    "        self.transform = transform\n",
    "        self.target_transform = target_transform\n",
    "    def __len__(self):\n",
    "        \"\"\"pytorch建议实现\n",
    "        \"\"\"\n",
    "        return len(self.img_labels)\n",
    "\n",
    "    def __getitem__(self, idx):\n",
    "        img_path = os.path.join(self.img_dir, self.img_labels.iloc[idx, 0])\n",
    "        image = decode_image(img_path)\n",
    "        label = self.img_labels.iloc[idx, 1]\n",
    "        if self.transform:\n",
    "            image = self.transform(image)\n",
    "        if self.target_transform:\n",
    "            label = self.target_transform(label)\n",
    "        return image, label"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6d8955f8",
   "metadata": {},
   "source": [
    "## Dataloader API"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "343a3294",
   "metadata": {},
   "outputs": [],
   "source": [
    "from torch.utils.data import DataLoader\n",
    "# batch_size：用于随机小批量梯度下降的大小\n",
    "# shuffle：训练周期结束后打乱数据\n",
    "# num_workers：是否使用辅助线程来加载数据，效率有待考究\n",
    "# pin_memory：是否放到GPU中\n",
    "# drop_last：最后的小批次丢掉\n",
    "# collate_fn：对获取到的小批次再次后处理，例如 padding、\n",
    "train_dataloader = DataLoader(training_data, batch_size=64, shuffle=True)\n",
    "test_dataloader = DataLoader(test_data, batch_size=64, shuffle=False)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "dl",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
